wok diff busybox/stuff/busybox-1.27-fbvnc.u @ rev 21937

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