wok rev 17271

busybox: add fbvnc
author Pascal Bellard <pascal.bellard@slitaz.org>
date Fri Oct 24 16:26:40 2014 +0200 (2014-10-24)
parents 7c22b4192384
children d03507a03d90
files busybox/receipt busybox/stuff/busybox-1.22-fbvnc.u busybox/stuff/busybox-1.22.config busybox/stuff/busybox-1.22.config-ssfs busybox/stuff/busybox-1.22.config-static
line diff
     1.1 --- a/busybox/receipt	Fri Oct 24 12:46:53 2014 +0200
     1.2 +++ b/busybox/receipt	Fri Oct 24 16:26:40 2014 +0200
     1.3 @@ -44,7 +44,7 @@
     1.4  diet.u
     1.5  losetup.u
     1.6  fatattr.u
     1.7 -dpkg_deb-xz.u
     1.8 +fbvnc.u
     1.9  EOT
    1.10      cp $stuff/$PACKAGE-${VERSION%.*}.config .config
    1.11  }
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/busybox/stuff/busybox-1.22-fbvnc.u	Fri Oct 24 16:26:40 2014 +0200
     2.3 @@ -0,0 +1,681 @@
     2.4 +   text    data     bss     dec     hex filename
     2.5 +   3118       0       0    3118     c2e util-linux/fbvnc.o
     2.6 +--- /dev/null
     2.7 ++++ busybox/util-linux/fbvnc.c
     2.8 +@@ -0,0 +1,551 @@
     2.9 ++/* vi: set sw=4 ts=4: */
    2.10 ++/*
    2.11 ++ * A small linux framebuffer VNC viewer
    2.12 ++ *
    2.13 ++ * pascal.bellard@ads-lu.com
    2.14 ++ *
    2.15 ++ * Based on Ali Gholami Rudi's fbvnc.c
    2.16 ++ *   http://repo.or.cz/w/fbvnc.git
    2.17 ++ *
    2.18 ++ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    2.19 ++ */
    2.20 ++
    2.21 ++//applet:IF_FBVNC(APPLET(fbvnc, BB_DIR_BIN, BB_SUID_DROP))
    2.22 ++
    2.23 ++//kbuild:lib-$(CONFIG_FBVNC) += fbvnc.o
    2.24 ++
    2.25 ++//config:config FBVNC
    2.26 ++//config:	bool "fbvnc"
    2.27 ++//config:	default n
    2.28 ++//config:	depends on PLATFORM_LINUX
    2.29 ++//config:	help
    2.30 ++//config:	  A linux framebuffer VNC viewer.
    2.31 ++
    2.32 ++//usage:#define fbvnc_trivial_usage
    2.33 ++//usage:	"[VNC_SERVER] [PORT]"
    2.34 ++//usage:#define fbvnc_full_usage "\n\n"
    2.35 ++//usage:     "A linux framebuffer VNC viewer."
    2.36 ++//usage:     "\nTo exit, move mouse to upper left corner and press ESC."
    2.37 ++
    2.38 ++#include "libbb.h"
    2.39 ++#include "vnc.h"
    2.40 ++
    2.41 ++/* Stuff stolen from the kernel's fb.h */
    2.42 ++#define FB_ACTIVATE_ALL 64
    2.43 ++enum {
    2.44 ++	FBIOGET_VSCREENINFO = 0x4600,
    2.45 ++	FBIOPUT_VSCREENINFO = 0x4601,
    2.46 ++	FBIOGET_FSCREENINFO = 0x4602,
    2.47 ++	FBIOGETCMAP = 0x4604,
    2.48 ++	FBIOPUTCMAP = 0x4605
    2.49 ++};
    2.50 ++
    2.51 ++struct fb_bitfield {
    2.52 ++	uint32_t offset;                /* beginning of bitfield */
    2.53 ++	uint32_t length;                /* length of bitfield */
    2.54 ++	uint32_t msb_right;             /* !=0: Most significant bit is right */
    2.55 ++};
    2.56 ++struct fb_var_screeninfo {
    2.57 ++	uint32_t xres;                  /* visible resolution */
    2.58 ++	uint32_t yres;
    2.59 ++	uint32_t xres_virtual;          /* virtual resolution */
    2.60 ++	uint32_t yres_virtual;
    2.61 ++	uint32_t xoffset;               /* offset from virtual to visible */
    2.62 ++	uint32_t yoffset;               /* resolution */
    2.63 ++
    2.64 ++	uint32_t bits_per_pixel;
    2.65 ++	uint32_t grayscale;             /* !=0 Graylevels instead of colors */
    2.66 ++
    2.67 ++	struct fb_bitfield red;         /* bitfield in fb mem if true color, */
    2.68 ++	struct fb_bitfield green;       /* else only length is significant */
    2.69 ++	struct fb_bitfield blue;
    2.70 ++	struct fb_bitfield transp;      /* transparency */
    2.71 ++
    2.72 ++	uint32_t nonstd;                /* !=0 Non standard pixel format */
    2.73 ++
    2.74 ++	uint32_t activate;              /* see FB_ACTIVATE_x */
    2.75 ++
    2.76 ++	uint32_t height;                /* height of picture in mm */
    2.77 ++	uint32_t width;                 /* width of picture in mm */
    2.78 ++
    2.79 ++	uint32_t accel_flags;           /* acceleration flags (hints) */
    2.80 ++
    2.81 ++	/* Timing: All values in pixclocks, except pixclock (of course) */
    2.82 ++	uint32_t pixclock;              /* pixel clock in ps (pico seconds) */
    2.83 ++	uint32_t left_margin;           /* time from sync to picture */
    2.84 ++	uint32_t right_margin;          /* time from picture to sync */
    2.85 ++	uint32_t upper_margin;          /* time from sync to picture */
    2.86 ++	uint32_t lower_margin;
    2.87 ++	uint32_t hsync_len;             /* length of horizontal sync */
    2.88 ++	uint32_t vsync_len;             /* length of vertical sync */
    2.89 ++	uint32_t sync;                  /* see FB_SYNC_x */
    2.90 ++	uint32_t vmode;                 /* see FB_VMODE_x */
    2.91 ++	uint32_t reserved[6];           /* Reserved for future compatibility */
    2.92 ++};
    2.93 ++
    2.94 ++#define DEFAULTFBDEV  FB_0
    2.95 ++
    2.96 ++struct fb_fix_screeninfo {
    2.97 ++	char id[16];			/* identification string eg "TT Builtin" */
    2.98 ++	unsigned long smem_start;	/* Start of frame buffer mem */
    2.99 ++					/* (physical address) */
   2.100 ++	uint32_t smem_len;		/* Length of frame buffer mem */
   2.101 ++	uint32_t type;			/* see FB_TYPE_*		*/
   2.102 ++	uint32_t type_aux;		/* Interleave for interleaved Planes */
   2.103 ++	uint32_t visual;		/* see FB_VISUAL_*		*/ 
   2.104 ++	uint16_t xpanstep;		/* zero if no hardware panning  */
   2.105 ++	uint16_t ypanstep;		/* zero if no hardware panning  */
   2.106 ++	uint16_t ywrapstep;		/* zero if no hardware ywrap    */
   2.107 ++	uint32_t line_length;		/* length of a line in bytes    */
   2.108 ++	unsigned long mmio_start;	/* Start of Memory Mapped I/O   */
   2.109 ++					/* (physical address) */
   2.110 ++	uint32_t mmio_len;		/* Length of Memory Mapped I/O  */
   2.111 ++	uint32_t accel;			/* Indicate to driver which	*/
   2.112 ++					/*  specific chip/card we have	*/
   2.113 ++	uint16_t reserved[3];		/* Reserved for future compatibility */
   2.114 ++};
   2.115 ++
   2.116 ++struct fb_cmap {
   2.117 ++	uint32_t start;			/* First entry	*/
   2.118 ++	uint32_t len;			/* Number of entries */
   2.119 ++	uint16_t *red;			/* Red values	*/
   2.120 ++	uint16_t *green;
   2.121 ++	uint16_t *blue;
   2.122 ++	uint16_t *transp;			/* transparency, can be NULL */
   2.123 ++};
   2.124 ++
   2.125 ++#define FB_VISUAL_TRUECOLOR		2	/* True color	*/
   2.126 ++
   2.127 ++#define COLORLEVELS   (1 << 8)
   2.128 ++
   2.129 ++struct scroll_data {
   2.130 ++	int size;
   2.131 ++	int srv_size;
   2.132 ++	int offset;
   2.133 ++	int pos;
   2.134 ++};
   2.135 ++
   2.136 ++struct globals {
   2.137 ++	struct termios term_orig;
   2.138 ++	struct pollfd ufds[3];
   2.139 ++#define kbd_fd		ufds[0].fd
   2.140 ++#define vnc_fd		ufds[1].fd
   2.141 ++#define rat_fd		ufds[2].fd
   2.142 ++	struct scroll_data scroll[2];
   2.143 ++#define cols		scroll[0].size
   2.144 ++#define srv_cols	scroll[0].srv_size
   2.145 ++#define oc		scroll[0].offset
   2.146 ++#define mc		scroll[0].pos
   2.147 ++#define rows		scroll[1].size
   2.148 ++#define srv_rows	scroll[1].srv_size
   2.149 ++#define or		scroll[1].offset
   2.150 ++#define mr		scroll[1].pos
   2.151 ++	int fb_fd;
   2.152 ++	void *fb_ptr;
   2.153 ++	int bpp;
   2.154 ++	int nr, ng, nb;
   2.155 ++	struct fb_var_screeninfo vinfo;
   2.156 ++	struct fb_fix_screeninfo finfo;
   2.157 ++	unsigned short red[COLORLEVELS], green[COLORLEVELS], blue[COLORLEVELS];
   2.158 ++};
   2.159 ++
   2.160 ++#define G (*ptr_to_globals)
   2.161 ++#define INIT_G() do { \
   2.162 ++	SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
   2.163 ++} while (0)
   2.164 ++
   2.165 ++static int fb_len(void)
   2.166 ++{
   2.167 ++	return G.finfo.line_length * G.vinfo.yres_virtual;
   2.168 ++}
   2.169 ++
   2.170 ++static void fb_ioctl_cmap(int fct, struct fb_cmap *cmap)
   2.171 ++{
   2.172 ++	if (G.finfo.visual == FB_VISUAL_TRUECOLOR)
   2.173 ++		return;
   2.174 ++	cmap->start = 0;
   2.175 ++	cmap->len = MAX(G.nr, MAX(G.ng, G.nb));
   2.176 ++	cmap->transp = NULL;
   2.177 ++	xioctl(G.fb_fd, fct, cmap);
   2.178 ++}
   2.179 ++
   2.180 ++static void fb_cmap_save(int save)
   2.181 ++{
   2.182 ++	struct fb_cmap cmap;
   2.183 ++	
   2.184 ++	cmap.red = G.red;
   2.185 ++	cmap.green = G.green;
   2.186 ++	cmap.blue = G.blue;
   2.187 ++	fb_ioctl_cmap(save ? FBIOGETCMAP : FBIOPUTCMAP, &cmap);
   2.188 ++}
   2.189 ++
   2.190 ++static void fb_build_cmap(unsigned short *color, int n)
   2.191 ++{
   2.192 ++	int i, inc = 65535 / (n - 1);
   2.193 ++	
   2.194 ++	for (i = 0; n--; i += inc)
   2.195 ++		*color++ = i;
   2.196 ++}
   2.197 ++
   2.198 ++static void fb_cmap(void)
   2.199 ++{
   2.200 ++	unsigned short red[COLORLEVELS], green[COLORLEVELS], blue[COLORLEVELS];
   2.201 ++	struct fb_cmap cmap;
   2.202 ++
   2.203 ++	fb_build_cmap(cmap.red = red,     G.nr);
   2.204 ++	fb_build_cmap(cmap.green = green, G.ng);
   2.205 ++	fb_build_cmap(cmap.blue = blue,   G.nb);
   2.206 ++	fb_ioctl_cmap(FBIOPUTCMAP, &cmap);
   2.207 ++}
   2.208 ++
   2.209 ++static void fb_init(void)
   2.210 ++{
   2.211 ++	G.fb_fd = xopen(DEFAULTFBDEV, O_RDWR);
   2.212 ++	xioctl(G.fb_fd, FBIOGET_VSCREENINFO, &G.vinfo);
   2.213 ++	xioctl(G.fb_fd, FBIOGET_FSCREENINFO, &G.finfo);
   2.214 ++	close_on_exec_on(G.fb_fd);
   2.215 ++	G.fb_ptr = mmap(NULL, fb_len(), PROT_READ | PROT_WRITE, MAP_SHARED, G.fb_fd, 0);
   2.216 ++	if (G.fb_ptr == MAP_FAILED)
   2.217 ++		bb_perror_msg_and_die("mmap");
   2.218 ++	G.bpp = (G.vinfo.bits_per_pixel + 7) >> 3;
   2.219 ++	G.nr = 1 << G.vinfo.red.length;
   2.220 ++	G.nb = 1 << G.vinfo.blue.length;
   2.221 ++	G.ng = 1 << G.vinfo.green.length;
   2.222 ++	fb_cmap_save(1);
   2.223 ++	fb_cmap();
   2.224 ++}
   2.225 ++
   2.226 ++static void fb_free(void)
   2.227 ++{
   2.228 ++	fb_cmap_save(0);
   2.229 ++	munmap(G.fb_ptr, fb_len());
   2.230 ++	close(G.fb_fd);
   2.231 ++}
   2.232 ++
   2.233 ++#define fb_rows vinfo.yres
   2.234 ++#define fb_cols vinfo.xres
   2.235 ++
   2.236 ++static void fb_set(int r, int c, void *mem, int len)
   2.237 ++{
   2.238 ++	memcpy(G.fb_ptr + (r + G.vinfo.yoffset) * G.finfo.line_length + 
   2.239 ++		(c + G.vinfo.xoffset) * G.bpp, mem, len * G.bpp);
   2.240 ++}
   2.241 ++
   2.242 ++#define line_buffer	bb_common_bufsiz1
   2.243 ++#define MAXPIX		(sizeof(line_buffer)/sizeof(uint32_t))
   2.244 ++
   2.245 ++static void skip(int len)
   2.246 ++{
   2.247 ++	int n;
   2.248 ++	while (len > 0 && (n = read(G.vnc_fd, line_buffer, 
   2.249 ++				    MIN(len, sizeof(line_buffer)))) > 0)
   2.250 ++		len -= n;
   2.251 ++}
   2.252 ++
   2.253 ++static void vnc_init(void)
   2.254 ++{
   2.255 ++	struct vnc_client_init clientinit;
   2.256 ++	struct vnc_server_init serverinit;
   2.257 ++	struct vnc_client_pixelfmt pixfmt_cmd;
   2.258 ++	int connstat = VNC_CONN_FAILED;
   2.259 ++
   2.260 ++	write(G.vnc_fd, "RFB 003.003\n", 12);
   2.261 ++	skip(12);
   2.262 ++
   2.263 ++	xread(G.vnc_fd, &connstat, sizeof(connstat));
   2.264 ++
   2.265 ++	if (ntohl(connstat) != VNC_CONN_NOAUTH)
   2.266 ++		bb_perror_msg_and_die("vnc auth");
   2.267 ++
   2.268 ++	clientinit.shared = 1;
   2.269 ++	write(G.vnc_fd, &clientinit, sizeof(clientinit));
   2.270 ++	read(G.vnc_fd, &serverinit, sizeof(serverinit));
   2.271 ++
   2.272 ++	fb_init();
   2.273 ++	G.srv_cols = ntohs(serverinit.w);
   2.274 ++	G.srv_rows = ntohs(serverinit.h);
   2.275 ++	G.cols = MIN(G.srv_cols, G.fb_cols);
   2.276 ++	G.rows = MIN(G.srv_rows, G.fb_rows);
   2.277 ++	G.mr = G.rows / 2;
   2.278 ++	G.mc = G.cols / 2;
   2.279 ++
   2.280 ++	skip(ntohl(serverinit.len));
   2.281 ++	pixfmt_cmd.type = VNC_CLIENT_PIXFMT;
   2.282 ++	pixfmt_cmd.format.bigendian = 0;
   2.283 ++	pixfmt_cmd.format.truecolor = 1;
   2.284 ++	pixfmt_cmd.format.bpp =
   2.285 ++	pixfmt_cmd.format.depth = G.bpp << 3;
   2.286 ++	pixfmt_cmd.format.rmax = htons(G.nr - 1);
   2.287 ++	pixfmt_cmd.format.gmax = htons(G.ng - 1);
   2.288 ++	pixfmt_cmd.format.bmax = htons(G.nb - 1);
   2.289 ++	pixfmt_cmd.format.rshl = G.vinfo.red.offset;
   2.290 ++	pixfmt_cmd.format.gshl = G.vinfo.green.offset;
   2.291 ++	pixfmt_cmd.format.bshl = G.vinfo.blue.offset;
   2.292 ++	write(G.vnc_fd, &pixfmt_cmd, sizeof(pixfmt_cmd));
   2.293 ++}
   2.294 ++
   2.295 ++static void vnc_refresh(int inc)
   2.296 ++{
   2.297 ++	struct vnc_client_fbup fbup_req;
   2.298 ++	fbup_req.type = VNC_CLIENT_FBUP;
   2.299 ++	fbup_req.inc = inc;
   2.300 ++	fbup_req.x = htons(G.oc);
   2.301 ++	fbup_req.y = htons(G.or);
   2.302 ++	fbup_req.w = htons(G.oc + G.cols);
   2.303 ++	fbup_req.h = htons(G.or + G.rows);
   2.304 ++	write(G.vnc_fd, &fbup_req, sizeof(fbup_req));
   2.305 ++}
   2.306 ++
   2.307 ++static void cleanup(void)
   2.308 ++{
   2.309 ++	const char *reset = "\x1b[?25h" "\x1b[2J\x1b[H";
   2.310 ++	fb_free();
   2.311 ++	tcsetattr_stdin_TCSANOW(&G.term_orig);
   2.312 ++	write(STDOUT_FILENO, reset, strlen(reset));
   2.313 ++	if (ENABLE_FEATURE_CLEAN_UP) {
   2.314 ++		close(G.vnc_fd);
   2.315 ++		close(G.rat_fd);
   2.316 ++	}
   2.317 ++}
   2.318 ++
   2.319 ++static void killed(int code) NORETURN;
   2.320 ++static void killed(int code)
   2.321 ++{
   2.322 ++	cleanup();
   2.323 ++	if (code > EXIT_FAILURE)
   2.324 ++		kill_myself_with_sig(code);
   2.325 ++	exit(code);
   2.326 ++}
   2.327 ++
   2.328 ++static void vnc_event(void)
   2.329 ++{
   2.330 ++	struct vnc_rect uprect;
   2.331 ++	union {
   2.332 ++		struct vnc_server_fbup fbup;
   2.333 ++		struct vnc_server_cuttext cuttext;
   2.334 ++		struct vnc_server_colormap colormap;
   2.335 ++	} msg;
   2.336 ++	int n;
   2.337 ++
   2.338 ++	switch (xread_char(G.vnc_fd)) {
   2.339 ++	case VNC_SERVER_FBUP:
   2.340 ++		xread(G.vnc_fd, &msg.fbup.pad, sizeof(msg.fbup) - 1);
   2.341 ++		n = ntohs(msg.fbup.n);
   2.342 ++		while (n--) {
   2.343 ++			int x, y, w, h, l, i;
   2.344 ++			xread(G.vnc_fd, &uprect, sizeof(uprect));
   2.345 ++			if (uprect.enc != 0)
   2.346 ++				killed(1);
   2.347 ++			i = 0;
   2.348 ++			x = ntohs(uprect.x) - G.oc;
   2.349 ++			y = ntohs(uprect.y) - G.or;
   2.350 ++			w = ntohs(uprect.w);
   2.351 ++			h = ntohs(uprect.h);
   2.352 ++			l = MIN(w, G.cols - x);
   2.353 ++			if (x < 0) {
   2.354 ++				l = MIN(w + x, G.cols);
   2.355 ++				i = -x;
   2.356 ++				x = 0;
   2.357 ++			}
   2.358 ++			for (; h--; y++) {
   2.359 ++				int a, b, c = i;
   2.360 ++				for (a = b = 0; w > b; b += a, c = 0) {
   2.361 ++					int len;
   2.362 ++					a = MIN(w - b, MAXPIX);
   2.363 ++					len = MIN(a, l - b) - c;
   2.364 ++					xread(G.vnc_fd, line_buffer, a * G.bpp);
   2.365 ++					if (y >= 0 && y < G.rows && len > 0)
   2.366 ++						fb_set(y, x + b, 
   2.367 ++						       line_buffer + (c * G.bpp),
   2.368 ++						       len);
   2.369 ++				}
   2.370 ++			}
   2.371 ++		}
   2.372 ++		break;
   2.373 ++	case VNC_SERVER_BELL:
   2.374 ++		break;
   2.375 ++	case VNC_SERVER_CUTTEXT:
   2.376 ++		xread(G.vnc_fd, &msg.cuttext.pad1, sizeof(msg.cuttext) - 1);
   2.377 ++		skip(ntohl(msg.cuttext.len));
   2.378 ++		break;
   2.379 ++	case VNC_SERVER_COLORMAP:
   2.380 ++		xread(G.vnc_fd, &msg.colormap.pad, sizeof(msg.colormap) - 1);
   2.381 ++		skip(ntohs(msg.colormap.n) * 3 * 2);
   2.382 ++		break;
   2.383 ++	default:
   2.384 ++		killed(1);
   2.385 ++	}
   2.386 ++}
   2.387 ++
   2.388 ++static int update_scroll(struct scroll_data *s)
   2.389 ++{
   2.390 ++	int shift = s->size / 5;
   2.391 ++	int max = s->srv_size - s->size;
   2.392 ++	int status = 0;
   2.393 ++	if (s->pos < s->offset) {
   2.394 ++		if ((s->offset -= shift) < 0)
   2.395 ++			s->offset = 0;
   2.396 ++	}
   2.397 ++	else if (s->pos >= s->offset + s->size && s->offset < max) {
   2.398 ++		if ((s->offset += shift) > max)
   2.399 ++			s->offset = max;
   2.400 ++	}
   2.401 ++	else status++;
   2.402 ++	s->pos = MAX(s->offset, MIN(s->offset + s->size - 1, s->pos));
   2.403 ++	return status;
   2.404 ++}
   2.405 ++
   2.406 ++static void rat_event(void)
   2.407 ++{
   2.408 ++	signed char ie[3];
   2.409 ++	struct vnc_client_ratevent me = {VNC_CLIENT_RATEVENT};
   2.410 ++	int mask = 0;
   2.411 ++	int refresh;
   2.412 ++
   2.413 ++	xread(G.rat_fd, &ie, sizeof(ie));
   2.414 ++	G.mc += ie[1];
   2.415 ++	G.mr -= ie[2];
   2.416 ++	refresh = 2 - update_scroll(&G.scroll[0]) - update_scroll(&G.scroll[1]);
   2.417 ++	if (ie[0] & 0x01)
   2.418 ++		mask |= VNC_BUTTON1_MASK;
   2.419 ++	if (ie[0] & 0x04)
   2.420 ++		mask |= VNC_BUTTON2_MASK;
   2.421 ++	if (ie[0] & 0x02)
   2.422 ++		mask |= VNC_BUTTON3_MASK;
   2.423 ++	me.y = htons(G.mr);
   2.424 ++	me.x = htons(G.mc);
   2.425 ++	me.mask = mask;
   2.426 ++	write(G.vnc_fd, &me, sizeof(me));
   2.427 ++	if (refresh)
   2.428 ++		vnc_refresh(0);
   2.429 ++}
   2.430 ++
   2.431 ++static int press(int key, int down)
   2.432 ++{
   2.433 ++	struct vnc_client_keyevent ke = {VNC_CLIENT_KEYEVENT};
   2.434 ++	ke.key = htonl(key);
   2.435 ++	ke.down = down;
   2.436 ++	return write(G.vnc_fd, &ke, sizeof(ke));
   2.437 ++}
   2.438 ++
   2.439 ++static void kbd_event(void)
   2.440 ++{
   2.441 ++	char key[1024];
   2.442 ++	int i, nr;
   2.443 ++
   2.444 ++	if ((nr = read(0, key, sizeof(key))) <= 0 )
   2.445 ++		killed(1);
   2.446 ++	for (i = 0; i < nr; i++) {
   2.447 ++		int k = -1;
   2.448 ++		int mod[4];
   2.449 ++		int nmod = 0;
   2.450 ++		switch (key[i]) {
   2.451 ++		case 0x08:
   2.452 ++		case 0x7f:
   2.453 ++			k = 0xff08;
   2.454 ++			break;
   2.455 ++		case 0x09:
   2.456 ++			k = 0xff09;
   2.457 ++			break;
   2.458 ++		case 0x1b:
   2.459 ++			if (G.oc + G.mc + G.or + G.mr == 0)
   2.460 ++				killed(0);
   2.461 ++			if (i + 2 < nr && key[i + 1] == '[') {
   2.462 ++				if (key[i + 2] == 'A')
   2.463 ++					k = 0xff52;
   2.464 ++				if (key[i + 2] == 'B')
   2.465 ++					k = 0xff54;
   2.466 ++				if (key[i + 2] == 'C')
   2.467 ++					k = 0xff53;
   2.468 ++				if (key[i + 2] == 'D')
   2.469 ++					k = 0xff51;
   2.470 ++				if (key[i + 2] == 'H')
   2.471 ++					k = 0xff50;
   2.472 ++				if (k > 0) {
   2.473 ++					i += 2;
   2.474 ++					break;
   2.475 ++				}
   2.476 ++			}
   2.477 ++			k = 0xff1b;
   2.478 ++			if (i + 1 < nr) {
   2.479 ++				mod[nmod++] = 0xffe9;
   2.480 ++				k = key[++i];
   2.481 ++			}
   2.482 ++			break;
   2.483 ++		case 0x0d:
   2.484 ++			k = 0xff0d;
   2.485 ++			break;
   2.486 ++		case 0x0c:	/* ^L: redraw */
   2.487 ++			vnc_refresh(0);
   2.488 ++		default:
   2.489 ++			k = (unsigned char) key[i];
   2.490 ++		}
   2.491 ++		if ((k >= 'A' && k <= 'Z') || strchr(":\"<>?{}|+_()*&^%$#@!~", k))
   2.492 ++			mod[nmod++] = 0xffe1;
   2.493 ++		if (k >= 1 && k <= 26) {
   2.494 ++			k += 'a' - 1;
   2.495 ++			mod[nmod++] = 0xffe3;
   2.496 ++		}
   2.497 ++		if (k > 0) {
   2.498 ++			int j;
   2.499 ++			mod[nmod] = k;
   2.500 ++			for (j = 0; j <= nmod; j++)
   2.501 ++				press(mod[j], 1);
   2.502 ++			press(k, 0);
   2.503 ++			for (j = 0; j < nmod; j++)
   2.504 ++				press(mod[j], 0);
   2.505 ++		}
   2.506 ++	}
   2.507 ++}
   2.508 ++
   2.509 ++static void term_setup(void)
   2.510 ++{
   2.511 ++	struct termios termios;
   2.512 ++	const char *init = "\x1b[?25l" "\x1b[2J\x1b[H" "** fbvnc **";
   2.513 ++
   2.514 ++	write(STDOUT_FILENO, init, strlen(init));
   2.515 ++	tcgetattr (STDIN_FILENO, &termios);
   2.516 ++	G.term_orig = termios;
   2.517 ++	cfmakeraw(&termios);
   2.518 ++	tcsetattr_stdin_TCSANOW(&termios);
   2.519 ++}
   2.520 ++
   2.521 ++int fbvnc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
   2.522 ++int fbvnc_main(int argc, char **argv)
   2.523 ++{
   2.524 ++	char *host = (char *) "127.0.0.1";
   2.525 ++	int port, pending = 0;
   2.526 ++	
   2.527 ++	INIT_G();
   2.528 ++	if (argc >= 2)
   2.529 ++		host = argv[1];
   2.530 ++	port = bb_lookup_port((argc >= 3) ?  argv[2] : "vnc", "tcp", 5900);
   2.531 ++	G.vnc_fd = create_and_connect_stream_or_die(host, port);
   2.532 ++	vnc_init();
   2.533 ++	G.rat_fd = open("/dev/input/mice", O_RDONLY);
   2.534 ++	term_setup();
   2.535 ++	atexit(cleanup);
   2.536 ++	bb_signals(BB_FATAL_SIGS, killed);
   2.537 ++
   2.538 ++	G.ufds[0].events =
   2.539 ++	G.ufds[1].events =
   2.540 ++	G.ufds[2].events = POLLIN;
   2.541 ++	vnc_refresh(0);
   2.542 ++	while (1) {
   2.543 ++		int status = poll(G.ufds, 3, 500);
   2.544 ++		if (status == -1 && errno != EINTR)
   2.545 ++			killed(1);
   2.546 ++		if (!status)
   2.547 ++			continue;
   2.548 ++		if (G.ufds[0].revents & POLLIN)
   2.549 ++			kbd_event();
   2.550 ++		if (G.ufds[1].revents & POLLIN) {
   2.551 ++			vnc_event();
   2.552 ++			pending = 0;
   2.553 ++		}
   2.554 ++		if (G.ufds[2].revents & POLLIN)
   2.555 ++			rat_event();
   2.556 ++		if (!pending++)
   2.557 ++			vnc_refresh(1);
   2.558 ++	}
   2.559 ++}
   2.560 +--- /dev/null
   2.561 ++++ busybox/util-linux/vnc.h
   2.562 +@@ -0,0 +1,122 @@
   2.563 ++#define VNC_CONN_FAILED		0
   2.564 ++#define VNC_CONN_NOAUTH		1
   2.565 ++#define VNC_CONN_AUTH		2
   2.566 ++
   2.567 ++#define VNC_AUTH_OK		0
   2.568 ++#define VNC_AUTH_FAILED		1
   2.569 ++#define VNC_AUTH_TOOMANY	2
   2.570 ++
   2.571 ++#define VNC_SERVER_FBUP		0
   2.572 ++#define VNC_SERVER_COLORMAP	1
   2.573 ++#define VNC_SERVER_BELL		2
   2.574 ++#define VNC_SERVER_CUTTEXT	3
   2.575 ++
   2.576 ++#define VNC_CLIENT_PIXFMT	0
   2.577 ++#define VNC_CLIENT_COLORMAP	1
   2.578 ++#define VNC_CLIENT_SETENC	2
   2.579 ++#define VNC_CLIENT_FBUP		3
   2.580 ++#define VNC_CLIENT_KEYEVENT	4
   2.581 ++#define VNC_CLIENT_RATEVENT	5
   2.582 ++#define VNC_CLIENT_CUTTEXT	6
   2.583 ++
   2.584 ++#define VNC_ENC_RAW		0
   2.585 ++#define VNC_ENC_COPYRECT	1
   2.586 ++#define VNC_ENC_RRE		2
   2.587 ++#define VNC_ENC_CORRE		4
   2.588 ++#define VNC_ENC_HEXTILE		5
   2.589 ++
   2.590 ++#define VNC_BUTTON1_MASK	0x1
   2.591 ++#define VNC_BUTTON2_MASK	0x2
   2.592 ++#define VNC_BUTTON3_MASK	0x4
   2.593 ++
   2.594 ++typedef unsigned char u8;
   2.595 ++typedef unsigned short u16;
   2.596 ++typedef unsigned int u32;
   2.597 ++
   2.598 ++struct vnc_pixelfmt {
   2.599 ++	u8 bpp;
   2.600 ++	u8 depth;
   2.601 ++	u8 bigendian;
   2.602 ++	u8 truecolor;
   2.603 ++	u16 rmax;
   2.604 ++	u16 gmax;
   2.605 ++	u16 bmax;
   2.606 ++	u8 rshl;
   2.607 ++	u8 gshl;
   2.608 ++	u8 bshl;
   2.609 ++
   2.610 ++	u8 pad1;
   2.611 ++	u16 pad2;
   2.612 ++};
   2.613 ++
   2.614 ++struct vnc_client_init {
   2.615 ++	u8 shared;
   2.616 ++};
   2.617 ++
   2.618 ++struct vnc_server_init {
   2.619 ++    u16 w;
   2.620 ++    u16 h;
   2.621 ++    struct vnc_pixelfmt fmt;
   2.622 ++    u32 len;
   2.623 ++    /* char name[len]; */
   2.624 ++};
   2.625 ++
   2.626 ++struct vnc_rect {
   2.627 ++	u16 x, y;
   2.628 ++	u16 w, h;
   2.629 ++	u32 enc;
   2.630 ++	/* rect bytes */
   2.631 ++};
   2.632 ++
   2.633 ++struct vnc_server_fbup {
   2.634 ++    u8 type;
   2.635 ++    u8 pad;
   2.636 ++    u16 n;
   2.637 ++    /* struct vnc_rect rects[n]; */
   2.638 ++};
   2.639 ++
   2.640 ++struct vnc_server_cuttext {
   2.641 ++	u8 type;
   2.642 ++	u8 pad1;
   2.643 ++	u16 pad2;
   2.644 ++	u32 len;
   2.645 ++	/* char text[length] */
   2.646 ++};
   2.647 ++
   2.648 ++struct vnc_server_colormap {
   2.649 ++	u8 type;
   2.650 ++	u8 pad;
   2.651 ++	u16 first;
   2.652 ++	u16 n;
   2.653 ++	/* u8 colors[n * 3 * 2]; */
   2.654 ++};
   2.655 ++
   2.656 ++struct vnc_client_pixelfmt {
   2.657 ++	u8 type;
   2.658 ++	u8 pad1;
   2.659 ++	u16 pad2;
   2.660 ++	struct vnc_pixelfmt format;
   2.661 ++};
   2.662 ++
   2.663 ++struct vnc_client_fbup {
   2.664 ++	u8 type;
   2.665 ++	u8 inc;
   2.666 ++	u16 x;
   2.667 ++	u16 y;
   2.668 ++	u16 w;
   2.669 ++	u16 h;
   2.670 ++};
   2.671 ++
   2.672 ++struct vnc_client_keyevent {
   2.673 ++	u8 type;
   2.674 ++	u8 down;
   2.675 ++	u16 pad;
   2.676 ++	u32 key;
   2.677 ++};
   2.678 ++
   2.679 ++struct vnc_client_ratevent {
   2.680 ++	u8 type;
   2.681 ++	u8 mask;
   2.682 ++	u16 x;
   2.683 ++	u16 y;
   2.684 ++};
     3.1 --- a/busybox/stuff/busybox-1.22.config	Fri Oct 24 12:46:53 2014 +0200
     3.2 +++ b/busybox/stuff/busybox-1.22.config	Fri Oct 24 16:26:40 2014 +0200
     3.3 @@ -527,6 +527,7 @@
     3.4  # Linux System Utilities
     3.5  #
     3.6  CONFIG_BLOCKDEV=y
     3.7 +CONFIG_FBVNC=y
     3.8  CONFIG_FSTRIM=y
     3.9  # CONFIG_MDEV is not set
    3.10  # CONFIG_FEATURE_MDEV_CONF is not set
     4.1 --- a/busybox/stuff/busybox-1.22.config-ssfs	Fri Oct 24 12:46:53 2014 +0200
     4.2 +++ b/busybox/stuff/busybox-1.22.config-ssfs	Fri Oct 24 16:26:40 2014 +0200
     4.3 @@ -527,6 +527,7 @@
     4.4  # Linux System Utilities
     4.5  #
     4.6  # CONFIG_BLOCKDEV is not set
     4.7 +# CONFIG_FBVNC is not set
     4.8  # CONFIG_FSTRIM is not set
     4.9  # CONFIG_MDEV is not set
    4.10  # CONFIG_FEATURE_MDEV_CONF is not set
     5.1 --- a/busybox/stuff/busybox-1.22.config-static	Fri Oct 24 12:46:53 2014 +0200
     5.2 +++ b/busybox/stuff/busybox-1.22.config-static	Fri Oct 24 16:26:40 2014 +0200
     5.3 @@ -527,6 +527,7 @@
     5.4  # Linux System Utilities
     5.5  #
     5.6  # CONFIG_BLOCKDEV is not set
     5.7 +# CONFIG_FBVNC is not set
     5.8  # CONFIG_FSTRIM is not set
     5.9  # CONFIG_MDEV is not set
    5.10  # CONFIG_FEATURE_MDEV_CONF is not set